﻿namespace SerialToConsole
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO.Ports;

    class SerialListener
    {
        private int _baudRate = 57600;
        private Parity _parity = Parity.None;
        private StopBits _stopBits = StopBits.One;
        private int _dataBits = 8;

        private SerialPort comPort = new SerialPort();

        private LinkedList<string> portsN = new LinkedList<String>();

        public SerialListener()
        {
            searchPort(SerialPort.GetPortNames());

            if (portsN.Count > 0)
            {
                setPort(portsN.First.Value, comPort);
            }
        }

        public SerialListener(string portName)
        {
            Console.WriteLine("Inializing serial port: " + portName);
            setPort(portName, comPort);
        }
        //-----------------------------------
        // Searches all ports
        private void searchPort(string[] ports)
        {
            Console.WriteLine("Searching post");
            int len = ports.Length;
            SerialDataReceivedEventHandler test = new SerialDataReceivedEventHandler(portTest);
            SerialPort[] comPorts = new SerialPort[len];
            for (int i = 0; i < len; i++)
            {
                SerialPort item = new SerialPort();
                comPorts[i] = item;

                if (item.IsOpen)
                {
                    continue;
                }

                setPort(ports[i], item);

                item.DataReceived += test;
                item.Open();
            }
            Console.Write("Waiting....");
            System.Threading.Thread.Sleep(2000);
            Console.Write("done.\n");

            foreach (var item in comPorts)
            {
                if (item.IsOpen)
                {
                    item.Close();
                    item.DataReceived -= test;
                }
            }
        }

        private void setPort(string item, SerialPort comPort)
        {
            comPort.BaudRate = _baudRate;
            comPort.Parity = _parity;
            comPort.StopBits = _stopBits;
            comPort.DataBits = _dataBits;
            comPort.PortName = item;
        }

        public void start()
        {
            try
            {
                if (comPort.IsOpen)
                {
                    return;
                }
                comPort.Open();

                System.Threading.Thread.Sleep(50);
                comPort.DiscardInBuffer();
                comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
            }
            catch (Exception)
            {
                // throw;
            }
        }

        public void stop()
        {
            if (comPort.IsOpen)
            {
                comPort.Close();
            }
        }

        // Checks if port responds  
        private void portTest(object sender, SerialDataReceivedEventArgs e)
        {
            Console.WriteLine("Got responce from post " + ((SerialPort)sender).PortName);
            string msg = ((SerialPort)sender).ReadExisting();
            portsN.AddLast(((SerialPort)sender).PortName);
        }

        private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //retrieve number of bytes in the buffer
            int bytes = comPort.BytesToRead;

            byte[] buff = new byte[bytes];

            int cnt = comPort.Read(buff, 0, bytes);
            string result = System.Text.Encoding.ASCII.GetString(buff);

            Console.Write(result);
        }

        internal void Write(string p)
        {
            Console.WriteLine("sending message: " + p);
            comPort.Write(p);
        }
    }
}